using System;
using System.Reflection;

using NUnit.Framework;

namespace Rsdn.SmartApp
{
	[TestFixture]
	public class ServiceManagerTest
	{
		private const string _name = "TestName";
		private const string _name2 = "TestName2";
		
		private ServiceManager _serviceManager;

		[SetUp]
		protected void SetUp()
		{
			_serviceManager = new ServiceManager(true);
		}
		
		[Test]
		public void PublishServiceInstance()
		{
			_serviceManager.Publish<ISampleService>(new SampleService(_name));
			AssertServiceReturned();
		}

		private void AssertServiceReturned()
		{
			ISampleService svc = _serviceManager.GetService<ISampleService>();
			Assert.IsNotNull(svc, "Service not returned");
			Assert.AreEqual(svc.GetName(), _name);
		}

		[Test]
		public void PublishServiceWithCreator()
		{
			bool svcCreated = false;
			ServiceCreator<ISampleService> creator = delegate {
				svcCreated = true;
				return new SampleService(_name);
			};
			_serviceManager.Publish(creator);
			Assert.IsFalse(svcCreated);
			AssertServiceReturned();
			Assert.IsTrue(svcCreated);
		}
		
		[Test]
		[ExpectedException(typeof (ArgumentException))]
		public void DuplicatePublishing()
		{
			_serviceManager.Publish<ISampleService>(new SampleService(_name));
			_serviceManager.Publish<ISampleService>(new SampleService(_name));
		}

		[Test]
		public void ParentServiceProviderCall()
		{
			_serviceManager.Publish<ISampleService>(new SampleService(_name));
			ServiceManager child = new ServiceManager(_serviceManager);
			ISampleService svc = child.GetService<ISampleService>();
			Assert.IsNotNull(svc);
			Assert.AreEqual(svc.GetName(), _name);
		}
		
		[Test]
		public void ImplementationOverriding()
		{
			_serviceManager.Publish<ISampleService>(new SampleService(_name));
			ServiceManager child = new ServiceManager(_serviceManager);
			child.Publish<ISampleService>(new SampleService(_name2));
			ISampleService svc = child.GetService<ISampleService>();
			Assert.IsNotNull(svc);
			Assert.AreEqual(svc.GetName(), _name2);
		}

		[Test]
		public void SelfPublishing()
		{
			Assert.AreEqual(_serviceManager.GetService<IServicePublisher>(),
				_serviceManager);
			ServiceManager child = new ServiceManager(true, _serviceManager);
			Assert.AreEqual(child.GetService<IServicePublisher>(), child);
		}

		[Test]
		public void Unpublishing()
		{
			IServiceCookie cookie = _serviceManager.Publish<ISampleService>(
				new SampleService(_name));
			_serviceManager.Unpublish(cookie);
			Assert.IsNull(_serviceManager.GetService<ISampleService>());
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void ServiceInstanceNull()
		{
			_serviceManager.Publish<ISampleService>((ISampleService)null);
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void ServiceCreatorNull()
		{
			_serviceManager.Publish<ISampleService>((ServiceCreator<ISampleService>)null);
		}

		[Test]
		[ExpectedException(typeof (ArgumentNullException))]
		public void ServiceCreatorReturnNull()
		{
			_serviceManager.Publish<ISampleService>(delegate { return null; });
			_serviceManager.GetService<ISampleService>();
		}

		[Test]
		public void ServicePublishingHelper()
		{
			ExtensionManager extMgr = new ExtensionManager(_serviceManager);
			extMgr.Scan(Assembly.GetExecutingAssembly().GetTypes(),
				new ServicePublishingStrategy(_serviceManager));
			Assert.IsNotNull(extMgr.GetService<ISampleService>());
		}
	}
}
